import { Ref, ref, watch } from "vue";
import * as lodash from "lodash-es";
import { MQWebSocket, MQWebSocketConfig } from "./mqWebsocket";
import { getLogger } from "../../../ts/log";
import { Instance } from "../../../ts";

/**
 * 全局初始化一个 WebSocket 对象
 *
 * 应该在 main.ts 中调用
 *
 * @param cfg MQWebSocketConfig MQ 的配置参数，主要是 url 配置
 */
export function initWebSocket(cfg: MQWebSocketConfig) {
  const logger = getLogger("ys-ts.mq.init");

  const isConnected = Instance.Instance().getOrSetFunc("ws.isConnected", () => {
    logger(`初始化 isConnected`);
    return ref(false);
  }) as Ref<boolean>;
  const ws = Instance.Instance().getOrSetFunc("websocket", () => {
    logger(`初始化 ws`);

    return new MQWebSocket({
      ...cfg,
      isConnected: isConnected,
    });
  }) as MQWebSocket;
}

interface IOption {
  doSub?: boolean;
  useCfg?: boolean;
  topics?: string[];
}

/**
 * 使用全局 WebSocket
 *
 * 如果需要执行订阅，可以设置 options.doSub 为 true，同时传入订阅的话题 options.topics。
 * 默认不执行订阅操作，同时订阅话题为全部
 *
 * 注意：启动订阅会注销上次的订阅内容
 *
 * @param options 输入配置
 */
export const useMqWebSocket = (options: IOption) => {
  const logger = getLogger("ys-ts.mq.one");

  // 输入参数解构
  const { doSub = false, topics = [] } = options;

  const isConnected = Instance.Instance().get("ws.isConnected") as Ref<boolean>;
  const ws = Instance.Instance().get("websocket") as MQWebSocket;

  /**
   * 当连接时执行操作，
   * 建立 watch 和直接执行
   * @param func
   */
  const doOnConnect = (func: () => void) => {
    if (isConnected.value) {
      logger(`直接执行`);
      func();
    }

    watch(isConnected, () => {
      if (isConnected.value) {
        logger(`监听执行`);
        func();
      }
    });
  };

  const sub = () => {
    ws.sub(lodash.join(topics, ","));
  };

  // 直接执行订阅
  if (doSub) {
    doOnConnect(sub);
  }

  return {
    ws,
    isConnected,
    doOnConnect,
  };
};
